<template>
  <div class="mapDiv">
    <div
      ref="myMap"
      :style="{ width: width, height: height }"
      class="container"
    >
    </div>
    <div
      class="toolControl"
      v-if="!disable"
    >
      <div v-show="!drawEdit">
        <div
          class="toolItem marker"
          :class="active == 'marker'?'active':''"
          title="点标记"
          @click="selectGeometry('marker')"
        ></div>
        <div
          class="toolItem polyline"
          :class="active == 'polyline'?'active':''"
          title="折线"
          @click="selectGeometry('polyline')"
        ></div>
        <div
          class="toolItem polygon"
          :class="active == 'polygon'?'active':''"
          title="多边形"
          @click="selectGeometry('polygon')"
        ></div>
        <div
          class="toolItem circle"
          :class="active == 'circle'?'active':''"
          title="圆形"
          @click="selectGeometry('circle')"
        ></div>
        <a-popover
          title="绘制操作"
          trigger="click"
        >
          <template slot="content">
            <ul class="tips-ul">
              <li>绘制：鼠标左键点击及移动即可绘制图形</li>
              <li>结束绘制：鼠标左键双击即可结束绘制折线、多边形、多边形会自动闭合；圆形单击即可结束</li>
              <li>中断：绘制过程中按下esc键可中断该过程</li>
            </ul>
          </template>
          <div class="toolItem btn-css">
            <a-icon type="question-circle" />
          </div>
        </a-popover>
      </div>
      <div v-show="drawEdit">
        <div
          class="toolItem delete"
          title="删除"
          @click="editGeometry('delete')"
        ></div>
        <div
          class="toolItem split"
          title="拆分"
          @click="editGeometry('split')"
        ></div>
        <div
          class="toolItem union"
          title="合并"
          @click="editGeometry('union')"
        ></div>
        <a-popover
          title="编辑操作"
          trigger="click"
        >
          <template slot="content">
            <ul class="tips-ul">
              <li>单选：鼠标左键点击图形</li>
              <li>多选：按下ctrl键后点击多个图形</li>
              <li>删除：选中图形后按下delete键或点击删除按钮可删除图形</li>
              <li>编辑：选中图形后出现编辑点，拖动编辑点可移动顶点位置，双击实心编辑点可删除顶点</li>
              <li>拆分：选中单个多边形后可绘制拆分线，拆分线绘制完成后自动进行拆分</li>
              <li>合并：选中多个相邻多边形后可进行合并，飞地形式的多边形不支持合并</li>
              <li>中断：按下esc键可中断当前操作，点选的图形将取消选中，编辑过程将中断</li>
            </ul>
          </template>
          <div class="toolItem btn-css">
            <a-icon type="question-circle" />
          </div>
        </a-popover>
      </div>
      <div
        class="toolItem btn-css"
        @click="editDraw"
      >{{drawBtnName}}</div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'TMapDraw',
  props: {
    /**
     * 地图宽度
     */
    width: {
      type: String,
      default: '100%',
    },
    /**
     * 地图高度
     */
    height: {
      type: String,
      default: '80vh',
    },
    /**
     * 地图配置
     */
    config: {
      type: Object,
      default: () => {
        return {}
      },
    },
    /**
     * 是否禁用绘画编辑
     */
    disable: {
      type: Boolean,
      default: false,
    },
    /**
     * 几何对象数据
     */
    data: {
      type: Object,
      default: () => {
        return {}
      },
    },
  },
  data() {
    return {
      map: null,
      resultConfig: {
        // 地图配置
        lat: 28.69959, // 纬度
        lng: 116.696714, // 经度
        zoom: 10, // 地图缩放级别,支持3～20。
        rotation: 0, // 地图在水平面上的旋转角度，顺时针方向为正，默认为0。
        pitch: 0, // 地图俯仰角度，取值范围为0~80，默认为0。
        offset: {
          // 地图中心与容器的偏移量，Object的格式为 {x:Number, y:Number}（右方下方为正，单位为像素）。
          x: 0,
          y: 0,
        },
      },
      active: 'marker',
      editor: null, // 几何图形及编辑器
      drawBtnName: '编辑', // 按钮名称
      drawEdit: false, // 图形编辑
      drawEditListener: true,
    }
  },
  watch: {
    'config.lat': {
      handler(newVal, oldVal) {
        if (newVal) {
          this.resultConfig.lat = newVal
          if (newVal != oldVal && this.map) {
            this.map.setCenter(new TMap.LatLng(this.resultConfig.lat, this.resultConfig.lng))
          }
        }
      },
      immediate: true,
    },
    'config.lng': {
      handler(newVal, oldVal) {
        if (newVal) {
          this.resultConfig.lng = newVal
          if (newVal != oldVal && this.map) {
            this.map.setCenter(new TMap.LatLng(this.resultConfig.lat, this.resultConfig.lng))
          }
        }
      },
      immediate: true,
    },
    'config.zoom': {
      handler(newVal, oldVal) {
        if (newVal) {
          this.resultConfig.zoom = newVal
          if (newVal != oldVal && this.map) {
            this.map.setZoom(newVal)
          }
        }
      },
      immediate: true,
    },
    'config.rotation': {
      handler(newVal, oldVal) {
        if (newVal) {
          this.resultConfig.rotation = newVal
          if (newVal != oldVal && this.map) {
            this.map.setRotation(newVal)
          }
        }
      },
      immediate: true,
    },
    'config.pitch': {
      handler(newVal, oldVal) {
        if (newVal) {
          this.resultConfig.pitch = newVal
          if (newVal != oldVal && this.map) {
            this.map.setPitch(newVal)
          }
        }
      },
      immediate: true,
    },
    'config.offset': {
      handler(newVal, oldVal) {
        if (newVal) {
          this.resultConfig.offset = newVal
          if (newVal != oldVal && this.map) {
            this.map.setOffset(newVal)
          }
        }
      },
      immediate: true,
    },
    disable(newVal, oldVal) {
      if (newVal) {
        // 禁用绘画编辑
        this.editor.disable()
      } else {
        // 启用绘画编辑
        this.editor.enable()
      }
    },
  },
  mounted() {
    this.initTMap()
  },
  methods: {
    /**
     * 初始化地图
     */
    initTMap() {
      this.map = new TMap.Map(this.$refs.myMap, {
        center: new TMap.LatLng(this.resultConfig.lat, this.resultConfig.lng), // 地图的中心地理坐标
        zoom: this.resultConfig.zoom, // 设置地图缩放级别
        rotation: this.resultConfig.rotation, // 设置地图旋转角度
        pitch: this.resultConfig.pitch, // 设置俯仰角度
        offset: this.resultConfig.offset,
      })
      this.initEditor()
    },
    /**
     * 初始化几何图形及编辑器
     */
    initEditor() {
      // 点标记 赋初始值
      let MarkerGeometries = []
      // 折线 赋初始值
      let PolylineGeometries = []
      // 多边形 赋初始值
      let PolygonGeometries = []
      // 圆形 赋初始值
      let CircleGeometries = []
      if (this.data && JSON.stringify(this.data) != '{}') {
        if (this.data.marker) {
          // 多个点标记
          this.data.marker.forEach((v) => {
            MarkerGeometries.push({
              position: new TMap.LatLng(v.lat, v.lng),
            })
          })
        }
        if (this.data.polyline) {
          // 多个折线
          this.data.polyline.forEach((v) => {
            let paths = []
            v.paths.forEach((vv) => {
              paths.push(new TMap.LatLng(vv.lat, vv.lng))
            })
            PolylineGeometries.push({
              paths,
            })
          })
        }
        if (this.data.polygon) {
          // 多个多边形
          this.data.polygon.forEach((v) => {
            let paths = []
            v.paths.forEach((vv) => {
              if (vv instanceof Array) {
                // 内空多边形
                let path = []
                vv.forEach((vvv) => {
                  path.push(new TMap.LatLng(vvv.lat, vvv.lng))
                })
                paths.push(path)
              } else {
                paths.push(new TMap.LatLng(vv.lat, vv.lng))
              }
            })
            PolygonGeometries.push({
              paths,
            })
          })
        }
        if (this.data.circle) {
          // 多个圆形
          this.data.circle.forEach((v) => {
            CircleGeometries.push({
              center: new TMap.LatLng(v.center.lat, v.center.lng),
              radius: v.radius,
            })
          })
        }
      }

      this.editor = new TMap.tools.GeometryEditor({
        map: this.map, // 编辑器绑定的地图对象
        overlayList: [
          // 可编辑图层
          {
            overlay: new TMap.MultiMarker({
              map: this.map,
              styles: {
                highlight: new TMap.MarkerStyle({
                  src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/marker-pink.png',
                }),
              },
              geometries: MarkerGeometries,
            }),
            id: 'marker',
            selectedStyleId: 'highlight',
          },
          {
            overlay: new TMap.MultiPolyline({
              map: this.map,
              styles: {
                highlight: new TMap.PolylineStyle({
                  color: '#00FF00',
                  width: 4, //折线宽度
                }),
              },
              geometries: PolylineGeometries,
            }),
            id: 'polyline',
            selectedStyleId: 'highlight',
          },
          {
            overlay: new TMap.MultiPolygon({
              map: this.map,
              styles: {
                highlight: new TMap.PolygonStyle({
                  color: 'rgba(255, 255, 0, 0.6)',
                }),
              },
              geometries: PolygonGeometries,
            }),
            id: 'polygon',
            selectedStyleId: 'highlight',
          },
          {
            overlay: new TMap.MultiCircle({
              map: this.map,
              styles: {
                highlight: new TMap.CircleStyle({
                  color: 'rgba(255, 255, 0, 0.6)',
                }),
              },
              geometries: CircleGeometries,
            }),
            id: 'circle',
            selectedStyleId: 'highlight',
          },
        ],
        actionMode: TMap.tools.constants.EDITOR_ACTION.DRAW, // 编辑器的工作模式
        activeOverlayId: 'marker', // 激活图层
        snappable: true, // 开启吸附
      })

      // 监听绘制结束事件，获取绘制几何图形
      // this.editor.on('draw_complete', (geometry) => {
      //   this.$emit('draw', this.active, geometry)
      // })

      if (this.disable) {
        this.editor.disable()
      }
    },
    /**
     * 选择几何图形进行绘制
     */
    selectGeometry(id) {
      this.active = id
      this.editor.setActiveOverlay(id)
    },
    /**
     * 切换编辑/绘制几何图形
     */
    editDraw() {
      this.drawEdit = !this.drawEdit
      // 编辑
      if (this.drawEdit) {
        this.drawBtnName = '绘制'
        this.editor.setActionMode(TMap.tools.constants.EDITOR_ACTION.INTERACT)
        this.editor.setSelectable(true)
        if (this.drawEditListener) {
          this.drawEditListener = false
          // 监听删除、修改、拆分、合并完成事件
          // let evtList = ['delete', 'adjust', 'split', 'union']
          // evtList.forEach((evtName) => {
          //   this.editor.on(evtName + '_complete', (evtResult) => {
          //     this.$emit('draw', evtName, evtResult)
          //   })
          // })
          // 监听拆分失败事件，获取拆分失败原因
          this.editor.on('split_fail', (res) => {
            this.$warning({
              title: '提示',
              content: res.message,
              centered: true,
            })
          })
          // 监听合并失败事件，获取合并失败原因
          this.editor.on('union_fail', (res) => {
            this.$warning({
              title: '提示',
              content: res.message,
              centered: true,
            })
          })
        }
      } else {
        // 绘制
        this.drawBtnName = '编辑'
        this.editor.setActionMode(TMap.tools.constants.EDITOR_ACTION.DRAW)
      }
    },
    /**
     * 编辑几何图形
     */
    editGeometry(id) {
      switch (id) {
        // 删除
        case 'delete':
          this.editor.delete()
          break
        // 拆分
        case 'split':
          this.editor.split()
          break
        // 合并
        case 'union':
          this.editor.union()
          break
        default:
          break
      }
    },
    getData() {
      this.editor.stop()
      let data = {}
      this.editor.getOverlayList().forEach((v) => {
        let geometries = v.overlay._rawGeometries
        if (geometries.length == 0) {
          return
        }
        let position
        switch (v.id) {
          // 点标记
          case 'marker':
            position = []
            geometries.forEach((geo) => {
              position.push({ lat: geo.position.lat, lng: geo.position.lng })
            })
            data[v.id] = position
            break
          // 折线
          case 'polyline':
            position = []
            geometries.forEach((geo) => {
              let paths = []
              geo.paths.forEach((path) => {
                paths.push(new TMap.LatLng(path.lat, path.lng))
              })
              let distance = TMap.geometry.computeDistance(paths).toFixed(2) + '米'
              position.push({
                paths: geo.paths,
                distance,
              })
            })

            data[v.id] = position
            break
          // 多边形
          case 'polygon':
            position = []
            geometries.forEach((geo) => {
              let paths = []
              // 多边形类型 0为正常的多边形 1为环形多边形
              let type
              // 面积平方米
              let area
              geo.paths.forEach((path) => {
                if (path instanceof Array) {
                  type = 1
                  let paths2 = []
                  path.forEach((p) => {
                    paths2.push(new TMap.LatLng(p.lat, p.lng))
                  })
                  if (area) {
                    area = area - TMap.geometry.computeArea(paths2)
                  } else {
                    area = TMap.geometry.computeArea(paths2)
                  }
                } else {
                  type = 0
                  paths.push(new TMap.LatLng(path.lat, path.lng))
                }
              })

              if (type == 0) {
                area = TMap.geometry.computeArea(paths).toFixed(2) + '平方米'
              } else {
                area = area.toFixed(2) + '平方米'
              }

              position.push({
                paths: geo.paths,
                area,
              })
            })
            data[v.id] = position
            break
          // 圆形
          case 'circle':
            position = []
            geometries.forEach((geo) => {
              position.push({ center: { lat: geo.center.lat, lng: geo.center.lng }, radius: geo.radius })
            })
            data[v.id] = position
            break

          default:
            break
        }
      })
      if (JSON.stringify(data) == '{}') {
        data = null
      }
      return data
    },
  },
  destroyed() {
    // 销毁地图
    this.map.destroy()
  }
}
</script>
<style scoped>
.mapDiv {
  position: relative;
}
.container {
  text-align: start;
}
.container >>> .rotate-circle {
  height: auto;
}
.toolControl {
  position: absolute;
  top: 10px;
  left: 0px;
  right: 0px;
  margin: auto;
  z-index: 1001;
  display: flex;
  justify-content: center;
}
.toolItem {
  width: 40px;
  height: 40px;
  float: left;
  margin: 1px;
  padding: 4px;
  border-radius: 3px;
  background-size: 30px 30px;
  background-position: 4px 4px;
  background-repeat: no-repeat;
  box-shadow: 0 1px 2px 0 #e4e7ef;
  background-color: #ffffff;
  border: 1px solid #ffffff;
  cursor: pointer;
}
.toolItem:hover {
  border-color: #789cff;
}
.active {
  border-color: #d5dff2;
  background-color: #d5dff2;
}
.marker {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/marker_editor.png');
}
.polyline {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/polyline.png');
}
.polygon {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/polygon.png');
}
.circle {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/circle.png');
}
.delete {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/delete.png');
}
.split {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/split.png');
}
.union {
  background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/union.png');
}
.btn-css {
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tips-ul {
  padding: 0;
}
</style>